package com.sunyzc.ebaotech.simulator.ybt;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.sunyzc.ebaotech.simulator.IOUtil;
import com.sunyzc.ebaotech.simulator.SimulatorConfig;

public class YBTClient {
	private static final Logger log = LoggerFactory.getLogger(YBTClient.class);
	private static final String BASE_PACKAGE = "com.sunyzc.ebaotech.simulator.ybt.";
	private static final Map<String, YBTClientConfig> ybtClientConfigMap = SimulatorConfig.loadClientConfigMap();

	public static void main(String[] args) {
		boolean needCheckBill = true;
		String host = "172.30.1.205";
		String currentDate = null;
		int totalCount = 1;
		requestAllYBTFront(host, currentDate, totalCount, needCheckBill);
	}

	private static void requestAllYBTFront(String host, String currentDate, int totalCount, boolean needCheckBill) {
		// requestYBTFront(ybtClientConfigMap.get("ABC"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("BOC"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("CCBNEW"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("RealCCBNEW"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("ICBC"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("DGRCB"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("GZRCB"), host, currentDate, totalCount, needCheckBill);
		// requestYBTFront(ybtClientConfigMap.get("SDRCB"), host, currentDate, totalCount, needCheckBill);
		requestYBTFront(ybtClientConfigMap.get("POST"), host, currentDate, totalCount, needCheckBill);
	}

	private static void requestYBTFront(YBTClientConfig clientConfig, String host, String currentDate, int totalCount, boolean needCheckBill) {
		if (clientConfig != null && clientConfig.getClientCode() != null) {
			String clientCode = clientConfig.getClientCode();
			List<IYBTProcessor> processorList = new ArrayList<IYBTProcessor>();
			try {
				for (int index = 1; index <= totalCount; index++) {
					IYBTProcessor processor = generateProcessor(clientConfig);
					log.info(processor.getClass().getSimpleName() + " 第 " + index + "/" + totalCount + " 次开始");
					processor.setServerHost(host);
					processor.setCurrentDate(currentDate);
					processorList.add(processor);
					if (clientCode.equals("ABC")) {
						requestYBTFront(processor, "1002", null);
						requestYBTFront(processor, "1004", null);
					} else if (clientCode.equals("BOC")) {
						requestYBTFront(processor, "1001", null);
						requestYBTFront(processor, "1002", null);
					} else if (clientCode.contains("CCBNEW")) {
						requestYBTFront(processor, "P53819113", null);
						requestYBTFront(processor, "P53819152", null);
					} else if (clientCode.equals("ICBC"))
						requestYBTFront(processor, "1013", null);
					else if (clientCode.equals("DGRCB") || clientCode.equals("GZRCB") || clientCode.equals("POST") || clientCode.equals("SDRCB")) {
						requestYBTFront(processor, "1021", null);
						requestYBTFront(processor, "1022", null);
					}
					log.info(processor.getClass().getSimpleName() + " 第 " + index + "/" + totalCount + " 次结束");
				}
			} catch (Throwable e) {
				log.error(e.getMessage(), e);
			}
			if (needCheckBill)
				try {
					if (clientCode.equals("ABC") || clientCode.equals("BOC"))
						requestYBTFront(processorList.get(0), "801", YBTCheckBillUtil.generateCheckBillXmlTemplateStr(processorList, "801"));
					else if (clientCode.contains("CCBNEW"))
						requestYBTFront(processorList.get(0), "P53817103", YBTCheckBillUtil.generateCheckBillXmlTemplateStr(processorList, "P53817103"));
					else if (clientCode.equals("ICBC") || clientCode.equals("DGRCB") || clientCode.equals("GZRCB") || clientCode.equals("POST") || clientCode.equals("SDRCB"))
						requestYBTFront(processorList.get(0), "8001", YBTCheckBillUtil.generateCheckBillXmlTemplateStr(processorList, "8001"));
				} catch (Throwable e) {
					log.error(e.getMessage(), e);
				}
		}
	}

	public static String requestYBTFront(IYBTProcessor processor, String requestTransType, String requestBodyTemplateStr) throws Exception {
		Socket socket = null;
		BufferedOutputStream outputStream = null;
		BufferedInputStream inputStream = null;
		try {
			long startTime = System.currentTimeMillis();
			socket = new Socket(processor.getServerHost(), processor.getClientConfig().getPort());
			log.info("Socket " + socket + " established ...");
			outputStream = new BufferedOutputStream(socket.getOutputStream());
			inputStream = new BufferedInputStream(socket.getInputStream());

			byte[] requestBodyContentBytes = processor.generateRequestBodyBytes(requestTransType, requestBodyTemplateStr, true);
			byte[] requestHeadContentBytes = processor.generateHeadBytes(requestTransType, requestBodyContentBytes);
			log.info("交易[" + requestTransType + "]请求报文头: " + processor.convertContentBytesToStr(requestHeadContentBytes));
			log.debug("交易[" + requestTransType + "]请求处理后的报文体: " + processor.convertContentBytesToStr(requestBodyContentBytes));

			outputStream.write(requestHeadContentBytes);
			outputStream.write(requestBodyContentBytes);
			outputStream.flush();

			String responseHeadContentStr = processor.readHeadConetentStr(requestTransType, inputStream);
			String responseBodyContentStr = processor.readBodyConetentStr(requestTransType, inputStream, responseHeadContentStr);
			log.info("交易[" + requestTransType + "]响应报文头: " + responseHeadContentStr);
			log.info("交易[" + requestTransType + "]响应报文体: " + responseBodyContentStr);
			log.info("交易[" + requestTransType + "]用时 " + (System.currentTimeMillis() - startTime) + " 毫秒");

			return responseBodyContentStr;
		} finally {
			IOUtil.closeQuietly(outputStream);
			IOUtil.closeQuietly(inputStream);
			IOUtil.closeQuietly(socket);
			log.info("Socket " + socket + " closed.");
		}
	}

	public static IYBTProcessor generateProcessor(YBTClientConfig clientConfig) throws Exception {
		String clientCode = clientConfig.getClientCode();
		IYBTProcessor processor = (IYBTProcessor) Class.forName(BASE_PACKAGE + (clientCode.contains("CCBNEW") ? "ccbnew" : clientCode.toLowerCase()) + "." + clientCode + "Processor").newInstance();
		processor.setClientConfig(clientConfig);
		return processor;
	}
}
